package com.dsp.soundscape.client.widgets;

import com.dsp.soundscape.client.ServiceLocator;
import com.dsp.soundscape.model.AlbumInfo;
import com.dsp.soundscape.model.SongInfo;
import com.dsp.soundscape.model.ZipInfo;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.LinkElement;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Widget;

public class AlbumDialog extends DialogBox {
	interface MyUiBinder extends UiBinder<Widget, AlbumDialog> {}
	private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);

	@UiField Button okButton;
	@UiField Button zipButton;
	@UiField Button m3uButton;
	
	@UiField Image albumArt;
	
	@UiField HTMLPanel albumSongs;
	@UiField HTMLPanel meterContainer;
	
	private Element meter;
	
	private AlbumInfo album;
	private String zipURL;
	
	private int progress;
	private int metered;
	
	public AlbumDialog(AlbumInfo album) {
		super();

		this.album = album;
		
		this.setGlassEnabled(true);
		this.setModal(true);

		this.setText(album.getAlbum());
		this.center();

		this.add(uiBinder.createAndBindUi(this));
		
		if (album.isImageAvailable()) {
			albumArt.setUrl(album.getImage());
		} else {
			albumArt.setUrl("images/noart.jpg");
		}
		
		albumArt.setStyleName("preview-image");
		
		for (SongInfo info : album.getSongs()) {
			Element songElement = DOM.createDiv();
			Element spanElement = DOM.createSpan();
			LinkElement linkElement = (LinkElement) DOM.createAnchor().cast();
			
			songElement.setClassName("songInfo");
			spanElement.setInnerText(info.getSongnumber() + ". ");
			linkElement.setHref(info.getFulluri());
			linkElement.setInnerText(info.getFilename());
			linkElement.setTarget("_blank");
			
			songElement.appendChild(spanElement);
			songElement.appendChild(linkElement);
			albumSongs.getElement().appendChild(songElement);
		}
		
		this.center();
	}
	
	private class ProgressCallback implements AsyncCallback<ZipInfo> {
		@Override
		public void onFailure(Throwable caught) {
			// TODO Auto-generated method stub
		}

		@Override
		public void onSuccess(ZipInfo result) {
			evaluateResult(result);
		}
	}
	
	@UiHandler("zipButton")
	void zipAlbum(ClickEvent event) {
		ServiceLocator.getZipService().requestZipFile(album, new ProgressCallback());
	}
	
	@UiHandler("m3uButton")
	void createM3U(ClickEvent event) {
		ServiceLocator.getZipService().getM3U(album, GWT.getHostPageBaseURL(), new AsyncCallback<String>() {

			@Override
			public void onFailure(Throwable caught) {
				// TODO Auto-generated method stub
			}

			@Override
			public void onSuccess(String result) {
				navigate(result);
			}
		});
	}
	
	@UiHandler("okButton")
	void okClose(ClickEvent event) {
		this.hide();
	}

	void startTimer() {
		Timer timer = new Timer(){
			@Override
			public void run() {
				ServiceLocator.getZipService().getProgress(album.getId(), new ProgressCallback());
			}
		};
		
		timer.schedule(100);
		new ProgressTimer().go();
	}
	
	void evaluateResult(ZipInfo result) {
		if (result == null || !result.isCompleted()) {
			renderMeter(result);
			startTimer();
		} else {
			zipURL = result.getUrl();
			
			Anchor link = new Anchor();
			link.setHref(zipURL);
			link.setText("Download Zip File");

			meterContainer.getElement().setInnerHTML("");
			meterContainer.getElement().appendChild(link.getElement());
		}
	}
	
	void renderMeter(ZipInfo info) {
		if (meter == null) {
			Element meterOuter = DOM.createDiv();
			meterOuter.setClassName("meterOuter");

			meter = DOM.createDiv();
			meter.setClassName("meterInner");
			
			meterOuter.appendChild(meter);
			meterContainer.getElement().appendChild(meterOuter);
		}
		
		progress = Math.round((new Float(info.getProgress()) / new Float(info.getFiles())) * albumArt.getWidth());
	}
	
	private class ProgressTimer extends Timer {
		@Override
		public void run() {
			if (metered < progress) {
				metered ++;
				meter.getStyle().setWidth(metered, Unit.PX);
			}
			
			if (metered < albumArt.getWidth()) {
				new ProgressTimer().go();
			}
		}
		
		public void go() {
			schedule(15);	
		}
	}
	
	public native void navigate(String href) /*-{
		$wnd.location.href = href;
	}-*/;
}
